/**
 * 
 */
package com.gragra.clustering;
import java.io.IOException;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import com.gragra.data.MixingCorpus;
import com.gragra.sampling.Annealing;
import com.gragra.sampling.RunSamplingPopulation;
import com.gragra.sampling.ThreadedUniformAccess;
import com.gragra.sampling.assignerFactories.VectorAssignerFactory;
import com.gragra.sampling.vector.VectorProbabilityAssigner;
import com.gragra.sampling.vector.VectorStructure;
/**
 * This class implements clustering based on MCMC Sampling-Optimization. The model that is used can be arbitrary,
 * as long as it can be implemented by giving the correct VectorAssignerFactory
 * @author Christoph Teichmann
 * created Apr 29, 2013 1:31:19 PM
 * @version 0.1
 */
public class SimpleSamplingBasedClusterer implements ClusteringAlgorithm
{
	/**
	 * creates a new Instance with the given parameters, stopping for the sampling is decided automatically
	 * @param samplingIntervalSize
	 * @param factory
	 */
	public SimpleSamplingBasedClusterer(int samplingIntervalSize,
			VectorAssignerFactory factory, int minSampling, int burnIn,
						 Annealing ann, int threads)
	{
		this.factory = factory;
		this.samplingSteps = minSampling;
		this.burnIn = burnIn;
		this.ann = ann;
		this.threads = threads;
	}
	/**
	 * 
	 */
	private final int threads;
	/**
	 * the annealing schedule used
	 */
	private final Annealing ann;
	/**
	 * the number of burn in steps
	 */
	private final int burnIn;
	/**
	 * the number of samplling steps that are at least used
	 */
	private final int samplingSteps;
	/**
	 * the VectorAssignerFactory used
	 */
	private final VectorAssignerFactory factory;
	/* (non-Javadoc)
	 * @see com.gragra.clustering.ClusteringAlgorithm#cluster(com.gragra.data.Corpus, int)
	 */
	@Override
	public void cluster(MixingCorpus<? extends VectorStructure> corpus, ThreadedUniformAccess tua) throws IOException, InterruptedException	
	{
		VectorProbabilityAssigner pa = this.factory.createNewInstance(corpus);
		RunSamplingPopulation rp = new RunSamplingPopulation(corpus);
		rp.setThreads(threads);
		rp.setAnn(ann);
		rp.run(pa, burnIn, samplingSteps, 1);
		assignments.clear();
		for(int i=0;i<corpus.size();++i)
		{this.assignments.put(i, corpus.getEntry(i).getBestIntCode());}
	}
	/**
	 * the assignments that resulted from clustering
	 */
	private final Int2IntOpenHashMap assignments = new Int2IntOpenHashMap();
	/* (non-Javadoc)
	 * @see com.gragra.clustering.ClusteringAlgorithm#getBest(com.gragra.sampling.vector.VectorStructure, int)
	 */
	@Override
	public int getBest(VectorStructure vs, int number)
	{return this.assignments.get(number);}
}